<template>
  <div class="jdf-visualizer">
    <div class="visualizer-controls">
      <!-- Layout Controls -->
      <el-button-group>
        <el-tooltip content="水平布局">
          <el-button
              size="small"
              :icon="DCaret"
              :type="dagreDirection === 'TB' ? 'primary' : ''"
              @click="setDagreDirection('TB')"
          />
        </el-tooltip>
        <el-tooltip content="垂直布局">
          <el-button
              size="small"
              :icon="CaretRight"
              :type="dagreDirection === 'LR' ? 'primary' : ''"
              @click="setDagreDirection('LR')"
          />
        </el-tooltip>
      </el-button-group>
    </div>

    <vue-flow
        :nodes="editorStore.flowElements.nodes"
        :edges="editorStore.flowElements.edges"
        :node-types="nodeTypes"
        :default-zoom="1"
        :min-zoom="0.1"
        :max-zoom="4"
        :fit-view-on-init="true"
        :nodes-draggable="true"
        :edges-updatable="true"
        :elements-selectable="true"
        :snap-to-grid="true"
        :snap-grid="[15, 15]"
        @node-click="onNodeClick"
        @pane-click="onPaneClick"
        @node-context-menu="handleNodeContextMenu"
        @pane-context-menu="onPaneContextMenu"
        @connect="onConnect"
        @edge-update-start="onEdgeUpdateStart"
        @edge-update="onEdgeUpdate"
        @edge-update-end="onEdgeUpdateEnd"
        @node-drag-stop="onNodeDragStop"
        @move-end="onMoveEnd"
        @pane-ready="onPaneReady"
        @selection-drag-start="onSelectionDragStart"
        @selection-drag="onSelectionDrag"
        @selection-drag-stop="onSelectionDragStop"
        @selection-context-menu="onSelectionContextMenu"
        class="jdf-flow"
    >
      <template #node-jdf="slotProps">
        <!-- Pass all slot props correctly using v-bind -->
        <JDFNode v-bind="slotProps" />
      </template>

      <Controls position="top-left">
        <ControlButton title="适应视图" @click="resetView">
          <el-icon><FullScreen /></el-icon>
        </ControlButton>
        <ControlButton title="放大" @click="zoomIn">
          <el-icon><Plus /></el-icon>
        </ControlButton>
        <ControlButton title="缩小" @click="zoomOut">
          <el-icon><Minus /></el-icon>
        </ControlButton>
        <ControlButton title="撤销" @click="undo" :disabled="!canUndo">
          <el-icon><Back /></el-icon>
        </ControlButton>
        <ControlButton title="重做" @click="redo" :disabled="!canRedo">
          <el-icon><Right /></el-icon>
        </ControlButton>
        <ControlButton title="同步更改到编辑器" @click="syncToEditor">
          <el-icon><Files /></el-icon>
        </ControlButton>
      </Controls>

      <MiniMap :pannable="true" :zoomable="true"/>

      <Background pattern-color="#aaa" :gap="16" />
    </vue-flow>

    <div v-if="editorStore.isLoading" class="loading-overlay">
      <el-icon class="is-loading" :size="30"><Loading /></el-icon>
    </div>

    <JDFNodeDetails v-if="editorStore.drawerNodeId" />

    <ContextMenu v-model:show="contextMenu.show" :options="contextMenuOptions" />
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, watch, ref, reactive, shallowRef, markRaw, nextTick } from 'vue'
// Correct imports, remove FitViewOptions
import { VueFlow, useVueFlow, Position, type Node, type Edge, type Connection, type NodeMouseEvent, type FlowEvents, Panel } from '@vue-flow/core'
import type { FlowNode } from '@/models/jdf'; // Ensure FlowNode is imported if used
import { Background } from '@vue-flow/background'
import { Controls, ControlButton } from '@vue-flow/controls' // Import ControlButton
import { MiniMap } from '@vue-flow/minimap'
// Ensure all used icons are imported
import {
  DCaret, CaretRight, Refresh, Loading, FullScreen, Minus, Plus, Right, Delete, CirclePlus, DocumentCopy, Back, Files
} from '@element-plus/icons-vue'
import type { MenuOptions } from '@imengyu/vue3-context-menu'
import { useEditorStore } from '@/stores/editorStore.ts'
import { useSettingsStore } from '@/stores/settingsStore'
import JDFNode from './nodes/JDFNode.vue'
import JDFNodeDetails from './JDFNodeDetails.vue'
// import { parseWithSelectedParser } from '@/parsers' // Likely not needed here
// import { applyDagreLayout } from '@/utils/layoutUtils' // Layout handled in store
// import { useContextMenu } from '@/composables/useContextMenu' // Using local logic
import ContextMenu from '@imengyu/vue3-context-menu'
import { ElMessage, ElMessageBox, ElIcon } from 'element-plus' // Import ElIcon

const editorStore = useEditorStore()
const settingsStore = useSettingsStore()

// Correctly destructure all needed functions from useVueFlow *once*
const {
  fitView,
  zoomIn,
  zoomOut,
  findNode,
  onConnect,
  onEdgeUpdateStart,
  onEdgeUpdate,
  onEdgeUpdateEnd,
  onNodeDragStop,
  onMoveEnd,
  canUndo,
  canRedo,
  undo,
  redo
} = useVueFlow()

const nodeTypes = shallowRef({
  jdfNode: markRaw(JDFNode),
})

const dagreDirection = computed(() => settingsStore.dagre.rankdir)

// Watch store changes and fit view when nodes appear
watch(() => editorStore.flowElements.nodes, (newNodes, oldNodes) => {
  if (newNodes && newNodes.length > 0 && (!oldNodes || oldNodes.length === 0)) {
    nextTick(() => fitView({ padding: 0.2 }))
  }
}, { deep: false }) // Use shallow watch if possible

// Layout related watchers
watch(() => settingsStore.dagre.rankdir, () => {
  editorStore._triggerReactivityAndUpdateLayout(true);
});
watch(() => settingsStore.dagre.nodesep, () => {
  editorStore._triggerReactivityAndUpdateLayout(true);
});
watch(() => settingsStore.dagre.ranksep, () => {
  editorStore._triggerReactivityAndUpdateLayout(true);
});

const setDagreDirection = (direction: 'TB' | 'LR') => {
  settingsStore.setDagreDirection(direction)
}

// --- Event Handlers ---
const onNodeClick = (event: NodeMouseEvent) => {
  if (event.node) {
    console.log("Node clicked: ", event.node.id)
    editorStore.selectNodeForDrawer(event.node.id)
  }
}

const onPaneClick = () => {
  console.log("Pane clicked")
  editorStore.selectNodeVisually(null)
}

const resetView = () => {
  fitView()
}

// --- Context Menu Logic ---
const contextMenu = reactive({
  show: false,
  targetNode: null as FlowNode | null,
  targetIsPane: false,
  x: 0,
  y: 0
})

const contextMenuOptions = computed((): MenuOptions => {
  const target = contextMenu.targetNode
  const options: any[] = []

  if (contextMenu.targetIsPane) {
    options.push({ label: '适应视图', onClick: fitView })
    // Add other pane actions if needed
  } else if (target) {
    // Use imported components directly for icons, remove markRaw
    options.push({ label: '展开所有', icon: DCaret, onClick: () => editorStore.expandAllChildren(target.id) })
    options.push({ label: '折叠所有', icon: CaretRight, onClick: () => editorStore.collapseAllChildren(target.id) })
    options.push({ type: 'divider' })
    options.push({ label: '添加子节点', icon: CirclePlus, onClick: () => handleAddChild(target.id) })
    options.push({ type: 'divider' })
    options.push({ label: '删除节点', icon: Delete, onClick: () => handleDeleteNode(target.id, target.data.nodeName) })
  }

  return {
    items: options,
    x: contextMenu.x,
    y: contextMenu.y,
    theme: settingsStore.darkMode ? 'dark' : 'light', // Correct access
    zIndex: 3000,
    minWidth: 150
  }
})

// Use correct NodeMouseEvent type and event.event for coordinates
const handleNodeContextMenu = (event: NodeMouseEvent) => {
  console.log('[JDFVisualizer handleNodeContextMenu] Event:', event);
  event.event.preventDefault() // Use event.event here
  const node = findNode(event.node.id)
  if (!node) {
    console.warn(`[JDFVisualizer handleNodeContextMenu] Node not found: ${event.node.id}`);
    return;
  }
  contextMenu.targetNode = node as FlowNode // Cast to FlowNode
  contextMenu.targetIsPane = false;
  // Add type assertion for MouseEvent to access clientX/Y
  if (event.event instanceof MouseEvent) {
    contextMenu.x = event.event.clientX // Use event.event here
    contextMenu.y = event.event.clientY // Use event.event here
  } else {
    // Handle TouchEvent if necessary, e.g., use touches[0]
    contextMenu.x = event.event.touches[0].clientX
    contextMenu.y = event.event.touches[0].clientY
  }
  contextMenu.show = true
}

// Keep onPaneContextMenu as is
const onPaneContextMenu = (event: MouseEvent) => {
  event.preventDefault()
  contextMenu.targetNode = null;
  contextMenu.targetIsPane = true;
  contextMenu.x = event.clientX
  contextMenu.y = event.clientY
  contextMenu.show = true
}

// --- Context Menu Action Helpers ---
const handleAddChild = (parentId: string) => {
  ElMessageBox.prompt('请输入新子节点的名称:', '添加子节点', {
    confirmButtonText: '添加',
    cancelButtonText: '取消',
    inputPattern: /^[\w.:-]+$/,
    inputErrorMessage: '无效的节点名称',
  }).then(({ value }) => {
    editorStore.addChildNode({ parentId, newNodeName: value });
  }).catch(() => {
    ElMessage.info('添加操作已取消');
  });
};

const handleDeleteNode = async (nodeId: string, nodeName: string) => {
  try {
    await ElMessageBox.confirm(
        `确定要删除"${nodeName || '节点'}"?此操作也会删除所有子节点。`,
        '删除确认',
        {
          confirmButtonText: '确定删除',
          cancelButtonText: '取消',
          type: 'warning',
        }
    )
    await editorStore.deleteNodeWithDescendants(nodeId)
    // Success message handled in store
  } catch {
    ElMessage.info('删除操作已取消。')
  }
}

// --- Sync Action ---
const syncToEditor = async () => {
  try {
    // Check if dirty before confirming
    if (!editorStore.isDirty) {
      ElMessage.info('可视化内容与编辑器一致，无需同步。');
      return;
    }
    await ElMessageBox.confirm(
        '确定要将可视化界面的更改同步到编辑器吗？此操作会覆盖编辑器当前内容并尝试保存。',
        '同步确认',
        {
          confirmButtonText: '确定同步',
          cancelButtonText: '取消',
          type: 'warning',
        }
    )
    await editorStore.syncVisualChangesToEditor()
    // Success/Error messages handled by store action
  } catch {
    ElMessage.info('同步操作已取消。')
  }
}

// --- Event Listeners for Logging (Keep as requested) ---
const onPaneReady = (event: FlowEvents['paneReady']) => {
  console.log('[VueFlow Event] Pane Ready:', event);
  // Initial fitView after pane is ready and nodes *might* be present
  nextTick(() => {
    if(editorStore.flowElements.nodes.length > 0) {
      fitView({ padding: 0.2 });
    }
  });
};
const onSelectionDragStart = (event: FlowEvents['selectionDragStart']) => {
  console.log('[VueFlow Event] Selection Drag Start:', event);
};
const onSelectionDrag = (event: FlowEvents['selectionDrag']) => {
  console.log('[VueFlow Event] Selection Drag:', event);
};
const onSelectionDragStop = (event: FlowEvents['selectionDragStop']) => {
  console.log('[VueFlow Event] Selection Drag Stop:', event);
};
// Handle selection context menu - show pane context menu for simplicity
const onSelectionContextMenu = (event: FlowEvents['selectionContextMenu']) => {
  console.log('[VueFlow Event] Selection Context Menu:', event);
  event.event.preventDefault();
  onPaneContextMenu(event.event as MouseEvent); // Reuse pane context menu handler, assert as MouseEvent
};

onMounted(() => {
  // Fit view logic moved to paneReady and node watcher
});
</script>

<style lang="scss" scoped>
/* Styles remain largely the same, ensure container has height */
.jdf-visualizer {
  display: flex;
  flex-direction: column;
  height: 100%; /* Crucial for VueFlow to have height */
  width: 100%;
  position: relative;
  overflow: hidden; /* Prevent visualiser scrollbars if flow fits */

  .visualizer-controls {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 4; // Above flow but below details maybe
  }

  .jdf-flow {
    flex-grow: 1; /* Take remaining space */
    position: relative;
    z-index: 1; // Base layer
  }
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(255, 255, 255, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

.dark .loading-overlay {
  background-color: rgba(0, 0, 0, 0.6);
}

/* Ensure controls are visible in dark mode */
.dark .vue-flow__controls {
  button {
    background: #2a2a2a;
    color: #fff;
    border-color: #555;
    &:hover {
      background: #3a3a3a;
    }
  }
}
/* Scoped styles for custom context menu items if needed */
:deep(.context-menu-item-icon) {
  margin-right: 8px;
}

/* Style fixes from previous attempts if needed */
.visualizer-container { /* Redundant if jdf-visualizer handles layout */
  /* ... */
}
.controls { /* Now part of VueFlow Controls component */
  /* ... */
}
.minimap { /* Now part of VueFlow MiniMap component */
  /* ... */
}
:deep(.vue-flow__contextmenu) { /* Library likely handles its own styling */
  z-index: 1000;
}

</style>